<template>
    <div :class="`${prefixCls}-autocomplete`">
        <div ref="control" :class="{ [prefixCls + '-autocomplete-control']: true }">
            <div :class="prefixCls + '-autocomplete-input'">
                <input 
                    ref="input" 
                    v-bind="$props" 
                    v-model="inputValue" 
                    :type="inputType" 
                    :placeholder="placeholder"
                    :disabled="disabled"
                    :class="[`${prefixCls}-input-control`,{'autocomplete-disabled':disabled}]" 
                    @compositionstart="_compositionStart"
                    @compositionend="_compositionEnd" 
                    @compositionupdate="_compositionUpdate" 
                    @input="_input"
                    @focus="_focus">
                <span :class="[prefixCls + '-input-suffix']" v-if="clearIcon && inputValue" @click="_clearInput"
                    :style="clearIcon ? 'cursor:pointer' : ''"><i class="icon icon-close"></i>
                </span>
            </div>

            <autocomplete-suggestions 
                :show="show" 
                :suggestions="suggestions"
                :transfer-class-name="transferClassName"
                ref="drop">
                <div v-if="suggestions.length == 0 && inputValue" class="no-data">无匹配数据</div>
                <li v-for="(item, index) in suggestions" :key="index" @click="_itemClick(item, $event)"
                    :class="{ 'disabled': item.disabled, 'active': selectValue(item) }">
                    <slot :item="item">
                        {{ item[valueKey] }}
                    </slot>
                </li>
            </autocomplete-suggestions>
        </div>
    </div>
</template>

<script>
import { prefixCls } from '../prefix'
import { isKorean } from '../../utils/shared'
import popup from '../../utils/popup'
import AutocompleteSuggestions from './autocomplete-suggestions'
import debounce from 'throttle-debounce/debounce';
import './autocomplete.css'

export default {
    name: `${prefixCls}Autocomplete`,
    components: { AutocompleteSuggestions },
    props: {
        value: {
            type: [String, Number],
            default: ''
        },
        valueKey: {//输入建议对象中用于显示的键名
            type: String,
            default: 'value'
        },
        type: {
            type: String,
            default: 'text'
        },
        clearIcon: { //是否显示清除按钮
            type: Boolean,
            default: false
        },
        triggerOnFocus: { //是否在输入框focus时显示建议框
            type: Boolean,
            default: false
        },
        placeholder: {//文本框提示内容
            type: String,
            default: '请输入内容'
        },
        showNum: {//展示数据数量
            type: Number,
            default: 9
        },
        transfer: {//是否将弹层放置于 body 内
            type: Boolean,
            default: false
        },
        disabled: Boolean,
        hideLoading: Boolean, //是否显示加载
        fetchSuggestions: Function, //数据回调
        transferClassName: String,
    },
    data() {
        return {
            prefixCls: prefixCls,
            inputValue: this.value,
            inputType: this.type,
            activeVal: this.value,//当前选中项
            show: false, //数据展示
            suggestions: [],
            suggestionDisabled: false,
            isComposing: false, //输入框是否输入完全
            loading: false,//数据加载loading
        }
    },
    mounted() {
        this.$nextTick(()=>{
            window.addEventListener('click', this._showHide)
            window.addEventListener('keydown', this.handleEscClose)
        })
    },
    watch:{
        value(val) {
            this.activeVal = val
            this.inputValue = val
        }
    },
    methods: {
        _showHide(e) {
            if (this.$el.contains(e.target)) {
                if(this.disabled) return
                this.show = !this.show
                this.isDown = false
                if (this.transfer && this.show) {
                    this.$nextTick(() => {
                        popup.create({ drop: this.$refs.drop.$el })
                        const DOMRect1 = this.$refs.control.getBoundingClientRect(),
                                _w1 = DOMRect1.width;
                        this.$refs.drop.$el.style.width = _w1 + 'px';
                    })
                }
                if (this.show) {
                    this.$nextTick(() => {
                        popup.position({
                            trigger: this.$refs.control,//触发层
                            drop: this.$refs.drop.$el,//下拉层
                            body: this.transfer,//是否将弹层置于body中
                        })
                    })
                }
            } else {
                this.show = false
            }
        },
        //监听键盘ESC关闭下拉
        handleEscClose(event) {
            const code = event.keyCode
            if(this.show){
                if(code === 27){
                    this.show = false
                    event.stopPropagation();
                }
            }
        },
        _compositionStart(event) {
            this.$emit('compositionstart', event);
            this.isComposing = true;
        },
        _compositionEnd(event) {
            this.$emit('compositionend', event);
            if (this.isComposing) {
                this.isComposing = false;
                this._input(event)
            }
        },
        _compositionUpdate(event) {
            this.$emit('compositionupdate', event);
            const text = event.target.value;
            const lastCharacter = text[text.length - 1] || '';
            this.isComposing = !isKorean(lastCharacter);
        },
        _focus(event) {
            this.$emit('on-focus', event);
            if (this.triggerOnFocus) {
                debounce(300, this.getData(this.inputValue))
            }
        },
        _input(event) {
            if (this.isComposing) return;

            this.$emit('input', event.target.value);
            this.suggestionDisabled = false;
            if (!this.triggerOnFocus && !event.target.value) {
                this.suggestionDisabled = true;
                this.suggestions = [];
                return;
            }
            debounce(300, this.getData(event.target.value))
        },
        //处理返回数据 
        getData(queryString) {
            if (this.suggestionDisabled) {
                return;
            }
            this.loading = true
            this.fetchSuggestions(queryString, (suggestions) => {
                this.loading = false
                if (this.suggestionDisabled) {
                    return;
                }
                if (Array.isArray(suggestions)) {
                    this.suggestions = suggestions;
                } else {
                    console.error('[MJUI Error][Autocomplete]autocomplete suggestions must be an array');
                }
            });
        },
        //选中项
        _itemClick(item, e) {
            if(item.disabled) return
            this.$emit('input', item[this.valueKey]);
            this.activeVal = item.value; //当前选中数据 
            this.inputValue = item.value; //把输入框数据替换为选择的数据
            this.$emit('on-select', item); //选择之后数据回调
            this.show = false
            e.stopPropagation();
        },
        //判断高亮显示选中数据
        selectValue(item) {
            return this.activeVal == item.value
        },
        //点击清除图标
        _clearInput() {
            this.inputValue = ''; //清除当前输入内容
            this.suggestions = []; //清空获取的展示数据
            this.$emit('on-clear')
            this.show = false
        },
    },
    beforeDestroy() {
        window.removeEventListener('click', this._showHide)
        window.removeEventListener('keydown', this.handleEscClose)
        if (this.transfer && this.show) {
            popup.delete({
                drop: this.$refs.drop.$el
            })
        }
    }
}
</script>
